/* 
 * File:   Thread.cpp
 * Author: mm021791
 * 
 * Created on 17 de octubre de 2012, 14:41
 */


#include "common_Thread.h"

#define THREAD_CANCELADO 0

using namespace TP::Threading;

Thread::Thread(const int pId){
    
    this->id = pId;
    this->activo = false;
    this->trabajando = false;
    pthread_mutex_init (&this->mutex, NULL);
}

Thread::~Thread(){
    try
    {
        //this->Finalizar();
        pthread_mutex_destroy (&this->mutex);
    }
    catch (Excepcion& pEx)
    {
    }
}

void Thread::Iniciar() throw (Excepcion&){
    try
    {
        this->Activar();
        
        switch (pthread_create( &this->thread, NULL, &correr_helper, this))
        {
            case EAGAIN: 
                throw Excepcion ("Insufficient resources to create another thread, or a system-imposed limit on the number of threads was encountered.  The latter case may occur in two ways: the RLIMIT_NPROC soft resource limit (set via setrlimit(2)), which limits the number of process for a real user ID, was reached; or the kernel's system-wide limit on the number ofthreads, /proc/sys/kernel/threads-max, was reached.");

            case EINVAL: 
                throw Excepcion ("Invalid settings in attr.");

            case EPERM:  
                throw Excepcion ("No permission to set the scheduling policy and parameters specified in attr.");
        }
        while (!this->Trabajando()) /*Esperar*/;
    }
    catch (Excepcion& pEx)      
    {
        pEx.expandirMensaje("Fallo al iniciar el thread.");
        throw pEx;
    }
}

void Thread::Finalizar() throw (Excepcion&){
    
    try
    {
        this->Desactivar();
        while (this->Trabajando()) /*Esperar*/;
        
    }
    catch (Excepcion& pEx)
    {
        pEx.expandirMensaje("Fallo al finalizar el thread.");
        throw;
    }
}

bool Thread::Activo (){
    return this->activo;
}

void Thread::Activar(){
    
    this->lock();

    this->activo = true;
    
    this->unlock();
}

void Thread::Desactivar(){
    
    this->lock();
    
    this->activo = false;
    
    this->unlock();
}

bool Thread::Trabajando(){
    return this->trabajando;
}

void Thread::Liberar(){
    
    this->lock();
    
    this->trabajando = false;
    
    this->unlock();
}

void Thread::Ocupar(){
    
    this->lock();
    
    this->trabajando = true;
    
    this->unlock();
}

int Thread::ID (){
    return this->id;
}

void* Thread::correr (void* pArgs){
    
    while (this->Activo())
    {
        this->Ocupar();
        this->tarea();
        this->Liberar();
    }
    return NULL;   
}

void Thread::lock(){
    pthread_mutex_lock(&mutex);
}

void Thread::unlock(){
    pthread_mutex_unlock(&mutex);
}
